<?php

include 'facade.php';

/**
 * 获取系统配置，含数据库配置
 * 该函数如果在未进入模块之前调用，将无法获取模块配置
 * @param string $name
 * @return mixed
 */
function Sys($name) {
    static $sys;
    if (!$sys) {

        $syscfg = Sys::getCfg();

        $dbcfgs = cache('system', 'dbcfg');
        if (!$dbcfgs) {
            $dbcfgs = QF()->System()->getAll();
            cache('system', 'dbcfg', $dbcfgs); // 永久缓存，减少数据库请求
        }

        if ($dbcfgs && is_array($dbcfgs)) {
            foreach ($dbcfgs as $dbcfg) {
                $sys[$dbcfg['name']] = $dbcfg['value'];
            }
        }

        // 数据库配置优先于文件配置
        $sys = $sys ? array_merge($syscfg, $sys) : $syscfg;
    }

    if (isset($sys[$name])) {
        return $sys[$name];
    }

    return null;
}

function msgbox($msg, $url = '', $style = 'success', $time = 2, $backstep = 0) {
    $params = array(
        'style' => $style,
        'msg' => $msg,
        'url' => $url,
        'time' => $time,
        'backstep' => $backstep,
    );
    die(Hmvc::load('Msgbox', 'index', $params));
}

function succ($msg = '操作成功', $url = '', $backstep = 0) {
    if (!$msg) {
        $msg = '操作成功';
    }
    msgbox($msg, $url, 'success', 2, $backstep);
}

function fail($msg = '操作失败', $url = '', $backstep = 0) {
    if (!$msg) {
        $msg = '操作失败';
    }
    msgbox($msg, $url, 'warning', 2, $backstep);
}

function is_error($error) {
    return is_array($error) && isset($error['is_error']) && $error['is_error'] === '.error';
}

function error($message = '', $code = -1) {
    return array('code' => $code, 'message' => $message, 'is_error' => '.error');
}

function error_code($error) {
    return is_error($error) ? $error['code'] : '参数不是个错误对象';
}

function error_message($error) {
    return is_error($error) ? $error['message'] : '';
}

function curl_post($url, $post = NULL, array $options = array()) {
    $fields = null;
    if (is_array($post)) {
        $fields = http_build_query($post);
    } else {
        $fields = $post;
    }

    $defaults = array(
        CURLOPT_POST => 1,
        CURLOPT_URL => $url,
        CURLOPT_FRESH_CONNECT => 1,
        CURLOPT_FORBID_REUSE => 1,
        // 如果是微信开发中CURLOPT_HEADER = 1 会导致请求失败
        CURLOPT_HEADER => 0,
        CURLOPT_RETURNTRANSFER => 1,
        CURLOPT_TIMEOUT => 30,
        CURLOPT_SSL_VERIFYPEER => false,
        CURLOPT_SSL_VERIFYHOST => false,
        // 如果请求页面使用了重定向301或者302，这个CURLOPT_FOLLOWLOCATION = 1 会导致函数出错
        CURLOPT_FOLLOWLOCATION => 1,
        CURLOPT_VERBOSE => 0,
        CURLOPT_POSTFIELDS => $fields
    );

    $ch = curl_init();
    curl_setopt_array($ch, ($options + $defaults));
    
    if (!$result = curl_exec($ch)) {
        wlog($url . "\n\n" . print_r($options + $defaults, true) . "\n\n" . $fields, 'curl');
        trigger_error(curl_error($ch));
    }
    
    curl_close($ch);
    return $result;
}

function curl_get($url, $get = NULL, array $options = array()) {

    $fields = '';
    if (is_array($get)) {
        $fields = http_build_query($get);
    } else {
        $fields = $get;
    }
    
    $url = $url . (strpos($url, '?') === FALSE ? '?' : '') . $fields;
    
    $defaults = array(
        CURLOPT_URL => $url,
        CURLOPT_HTTPGET => true,
        // 如果是微信开发中CURLOPT_HEADER = 1 会导致请求失败
        CURLOPT_HEADER => 0,
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_TIMEOUT => 30,
        CURLOPT_SSL_VERIFYPEER => false,
        CURLOPT_SSL_VERIFYHOST => false,
        // 如果请求页面使用了重定向301或者302，这个CURLOPT_FOLLOWLOCATION = 1 会导致函数出错
        CURLOPT_FOLLOWLOCATION => 1,
        CURLOPT_USERAGENT => 'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.0.3) Gecko/2008092417 Firefox/3.0.3'
    );

    $ch = curl_init();
    curl_setopt_array($ch, ($options + $defaults));
    
    if (!$result = curl_exec($ch)) {
        wlog($url . "\n\n" . print_r($options + $defaults, true), 'curl');
        trigger_error(curl_error($ch));
    }
    
    curl_close($ch);
    return $result;
}

/*
 * @purpose: 使用curl并行处理url
 * @return: array 每个url获取的数据
 * @param: $urls array url列表
 * @param: $callback 处理返回数据的回调函数
 */

function curl_multi($urls = array(), $callback = null) {
    $response = array();
    if (empty($urls)) {
        return $response;
    }
    $chs = curl_multi_init();
    $map = array();
    foreach ($urls as $url) {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_TIMEOUT, 10);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_HEADER, 0);
        curl_setopt($ch, CURLOPT_NOSIGNAL, true);
        curl_multi_add_handle($chs, $ch);
        $map[strval($ch)] = $url;
    }
    do {
        if (($state = curl_multi_exec($chs, $active)) != CURLM_CALL_MULTI_PERFORM) {
            if ($state != CURLM_OK) {
                break;
            } //如果没有准备就绪，就再次调用curl_multi_exec

            while ($done = curl_multi_info_read($chs)) {
                $info = curl_getinfo($done["handle"]);
                $error = curl_error($done["handle"]);
                $result = curl_multi_getcontent($done["handle"]);
                $url = $map[strval($done["handle"])];
                $rtn = compact('info', 'error', 'result', 'url');
                if ($callback) {
                    $callback($rtn);
                }
                $response[$url] = $rtn;
                curl_multi_remove_handle($chs, $done['handle']);
                curl_close($done['handle']);
                //如果仍然有未处理完毕的句柄，那么就select
                if ($active > 0) {
                    curl_multi_select($chs, 0.5); //此处会导致阻塞大概0.5秒。
                }
            }
        }
    } while ($active > 0); //还有句柄处理还在进行中
    curl_multi_close($chs);
    return $response;
}

/**
 * 
 * @param string $dirName 目录
 * @param bool $recursive 是否递归
 * @param bool $flat 是否展平为一维数组
 * @return array|bool
 */
function dirTree($dirName, $recursive = true, $flat = false) {

    $dirName = rtrim($dirName, '/');

    if (is_dir($dirName)) {

        if ($dh = opendir($dirName)) {

            $tree = array();

            while (( $file = readdir($dh) ) !== false) {

                if ($file != "." && $file != "..") {

                    $filePath = $dirName . "/" . $file;

                    if (is_dir($filePath)) { // 目录,递归
                        if ($recursive) {
                            if ($flat) {
                                $tree = array_merge($tree, dirTree($filePath, $recursive, $flat));
                            } else {
                                $tree[$file] = dirTree($filePath, $recursive, $flat);
                            }
                        }
                    } else { // 文件,添加到当前数组
                        if ($flat) {
                            $tree[] = $filePath;
                        } else {
                            $tree[] = $file;
                        }
                    }
                }
            }

            closedir($dh);
        } else {

            return false; // 无法打开目录
        }

        return $tree;
    } else {

        return false; // 不是目录
    }
}

function deleteDir($dirName) {

    $op = dir($dirName);

    while (false != ($item = $op->read())) {

        if ($item == '.' || $item == '..') {
            continue;
        }

        if (is_dir($op->path . '/' . $item)) {

            if (!deleteDir($op->path . '/' . $item)) {
                return false;
            }

            if (!rmdir($op->path . '/' . $item)) {
                return false;
            }
        } else {

            if (!unlink($op->path . '/' . $item)) {
                return false;
            }
        }
    }

    return rmdir($dirName);
}

function encodeUid($uid) {
    return strtoupper(Idcode::toSerialCode($uid));
}

function decodeUid($code) {
    return Idcode::codeToId(strtolower($code));
}

function sendMail($email, $title, $content) {
    try {
        $mail = new PHPMailer(true);
        $mail->IsSMTP();
        $mail->CharSet = 'UTF-8'; //设置邮件的字符编码，这很重要，不然中文乱码
        $mail->SMTPAuth = true; //开启认证
        $mail->Port = 25;
        $mail->Host = Sys('smtp_server');
        $mail->Username = Sys('smtp_user');
        $mail->Password = Sys('smtp_password');
        $mail->AddReplyTo(Sys('smtp_replyto'), Sys('smtp_nickname')); //回复地址
        $mail->From = Sys('smtp_from_mail');
        $mail->FromName = Sys('smtp_from_nickname');
        $mail->AddAddress($email);
        $mail->Subject = $title;
        $mail->Body = $content;
        $mail->AltBody = "To view the message, please use an HTML compatible email viewer!"; //当邮件不支持html时备用显示，可以省略
        $mail->WordWrap = 80; // 设置每行字符串的长度
        $mail->IsHTML(true);
        $result = $mail->Send();
        return $result;
    } catch (Exception $ex) {
        wlog($ex->getMessage(), 'mail');
        return false;
    }
}

function inWeixin() {
    if (strpos(strtolower($_SERVER['HTTP_USER_AGENT']), 'micromessenger') !== false) {
        if (inMobile()) {
            return true;
        } else {
            return false;
        }
    }
    return false;
}

/** 	
 * 判断是否是通过手机访问	
 */
function inMobile() {
    
    // 如果有HTTP_X_WAP_PROFILE则一定是移动设备
    if (isset($_SERVER['HTTP_X_WAP_PROFILE'])) {
        return true;
    }
    
    //判断手机发送的客户端标志,兼容性有待提高
    if (isset($_SERVER['HTTP_USER_AGENT'])) {
        $clientkeywords = array("Android", "iPhone", "Harmony", "SymbianOS", "Windows Phone", "iPod");
        // 从HTTP_USER_AGENT中查找手机浏览器的关键字
        if (preg_match("/(" . implode('|', $clientkeywords) . ")/i", strtolower($_SERVER['HTTP_USER_AGENT']))) {
            return true;
        }
    }
    
    //协议法，因为有可能不准确，放到最后判断
    if (isset($_SERVER['HTTP_ACCEPT'])) {
        // 如果只支持wml并且不支持html那一定是移动设备
        // 如果支持wml和html但是wml在html之前则是移动设备
        if ((strpos($_SERVER['HTTP_ACCEPT'], 'vnd.wap.wml') !== false) && (strpos($_SERVER['HTTP_ACCEPT'], 'text/html') === false ||
                (strpos($_SERVER['HTTP_ACCEPT'], 'vnd.wap.wml') <
                    strpos($_SERVER['HTTP_ACCEPT'], 'text/html')))) {
            return true;
        }
    }
    
    return false;
}

function uniorder($prefix, $id, $suffix = '') {
    $order_no = $prefix . str_pad($id, 9, '0') . date('YmdHis') . randString(6, 0) . $suffix;
    if (strlen($order_no) > 32) {
        return false;
    }
    return $order_no;
}

function cut_date($date) {
    return date('Y-m-d', strtotime($date));
}

function md_date($date) {
    return date('d/m', strtotime($date));
}

function md_cdate($date) {
    return date('m月d日', strtotime($date));
}

/**
 * 将html内包含的base64编码的图片转成文件
 *
 * @param $content
 * @param $dstdir
 * @param $urldir
 * @return string
 */
function html_convert_base64image($content, $dstdir, $urldir) {

    $content = htmlspecialchars_decode($content);

    $content = preg_replace_callback("/[\'\"]data:image\/(\w+);base64,(.*?)[\'\"]/is", function ($matches) use ($dstdir, $urldir) {
        if (isset($matches[2])) {

            if ($matches[1] == 'jpeg') {
                $fileExt = '.jpg';
            } else {
                $fileExt = '.' . $matches[1];
            }

            $filename = md5(millisecond() . randString()) . $fileExt;

            $base64_image = str_replace(' ', '+', $matches[2]);

            $result = file_put_contents($dstdir . $filename, base64_decode($base64_image));
            if ($result) {
                return "\"" . $urldir . $filename . "\"";
            } else {
                return "";
            }
        }
    }, $content);

    return htmlspecialchars($content);
}

/**
 * 格式化文件大小和单位
 *
 * @param $size
 * @return int|string
 */
function formatsize($size) {
    if (!$size) {
        return 0;
    }
    $prec = 3;
    $size = round(abs($size));
    $units = array(0 => " B", 1 => " KB", 2 => " MB", 3 => " GB", 4 => " TB");
    if ($size == 0) {
        return str_repeat(" ", $prec) . "0" . $units[0];
    }
    $unit = min(4, floor(log($size) / log(2) / 10));
    $size = $size * pow(2, -10 * $unit);
    $digi = $prec - 1 - floor(log($size) / log(10));
    $size = round($size * pow(10, $digi)) * pow(10, -$digi);
    return $size . $units[$unit];
}
